package com.stars.system.fitness.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.RandomUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.stars.system.fitness.domain.FitnessBasic;
import com.stars.system.fitness.domain.FitnessPlan;
import com.stars.system.fitness.domain.FitnessPlanVO;
import com.stars.system.fitness.mapper.FitnessBasicMapper;
import com.stars.system.fitness.mapper.FitnessPlanMapper;
import com.stars.system.fitness.mapper.FitnessRecordMapper;
import com.stars.system.fitness.service.IFitnessPlanService;
import io.lettuce.core.RedisCommandExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.alibaba.fastjson2.JSON.parseArray;
import static com.stars.system.fitness.service.impl.FitnessBasicServiceImpl.PLACE;

/**
 * 健身计划Service业务层处理
 * 
 * @author shuaibizhe
 * @date 2022-08-14
 */
@Service
public class FitnessPlanServiceImpl implements IFitnessPlanService 
{
    @Autowired
    private FitnessPlanMapper fitnessPlanMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private FitnessRecordMapper fitnessRecordMapper;

    @Autowired
    private FitnessBasicMapper fitnessBasicMapper;

    static final String today = DateUtils.getDate();

    static final String REFRESH = "refresh";
    
    static final String FINISH = "2";

    static final String NOT_FINISH = "0";

    static final Map ACCOUNT = new HashMap(){
        {
            put("3", "高");
            put("2", "中");
            put("1", "低");
        }
    };
    /**
     * 查询健身计划
     * 
     * @param planId 健身计划主键
     * @return 健身计划
     */
    @Override
    public FitnessPlanVO selectFitnessPlanByPlanId(String planId)
    {
        FitnessPlanVO fitnessPlanVO = fitnessPlanMapper.selectFitnessPlanByPlanId(planId);
        List plan_info = JSONObject.parseObject((String) fitnessPlanVO.getPlanInfo(), ArrayList.class);
        fitnessPlanVO.setPlanInfo(plan_info);
        return fitnessPlanVO;
    }

    /**
     * 查询健身计划列表
     * 
     * @param fitnessPlan 健身计划
     * @return 健身计划
     */
    @Override
    public List<FitnessPlan> selectFitnessPlanList(FitnessPlan fitnessPlan)
    {
        List<FitnessPlan> list = fitnessPlanMapper.selectFitnessPlanList(fitnessPlan);
        Map place_dict = (Map) redisCache.getCacheMap("basicDict").get(PLACE);
        for (int i = 0;i < list.size();i++) {
            StringBuilder sb = new StringBuilder();
            List<Map> infos = parseArray(list.get(i).getPlanInfo(), Map.class);
            for (Map info : infos) {
                sb.append(place_dict.get(info.get("key"))).append("：");
                int count = Integer.valueOf((String) info.get("value"));
                while (count > 0) {
                    sb.append("☀");
                    count-- ;
                }
                sb.append("     ");
            }
            list.get(i).setPlanInfo(sb.toString());
        }
        return list;
    }

    /**
     * 新增健身计划
     * 
     * @param fitnessPlan 健身计划
     * @return 结果
     */
    @Override
    public int insertFitnessPlan(FitnessPlan fitnessPlan)
    {
        // 根据计划周期推算计划结束日期
        Date planEnd = DateUtils.offsetDate(fitnessPlan.getPlanBeg(), fitnessPlan.getPlanCycle(), fitnessPlan.getCycleNum());

        fitnessPlan.setCreateTime(DateUtils.getNowDate());
        fitnessPlan.setCreateUser(SecurityUtils.getUserId());
        fitnessPlan.setPlanId(UUID.fastUUID().toString());
        fitnessPlan.setPlanEnd(planEnd);
        return fitnessPlanMapper.insertFitnessPlan(fitnessPlan);
    }

    /**
     * 查看该周期内是否已存在健身计划
     * @param fitnessPlan 健身计划
     * @return 存在即返回该优先级，不存在则返回0
     */
    @Override
    public int ifExistPlanInTimeScope(FitnessPlan fitnessPlan) {
        // 根据计划周期推算计划结束日期
        Date planEnd = DateUtils.offsetDate(fitnessPlan.getPlanBeg(), fitnessPlan.getPlanCycle(), fitnessPlan.getCycleNum());
        // 是否已存在本周期的计划,查询优先级最高的
        FitnessPlan fitnessPlanInTimeScope = fitnessPlanMapper.selectFitnessPlanInTimeScopeHighest(new FitnessPlan(){
            {
                setCreateUser(SecurityUtils.getUserId());
                setPlanEnd(planEnd);
                setPlanBeg(fitnessPlan.getPlanBeg());
            }
        });
        if (fitnessPlanInTimeScope != null) {
            return fitnessPlanInTimeScope.getPlanPriority();
        }
        return 0;
    }

    /**
     * 修改健身计划
     * 
     * @param fitnessPlan 健身计划
     * @return 结果
     */
    @Override
    public int updateFitnessPlan(FitnessPlan fitnessPlan)
    {
        return fitnessPlanMapper.updateFitnessPlan(fitnessPlan);
    }

    /**
     * 批量删除健身计划
     * 
     * @param planIds 需要删除的健身计划主键
     * @return 结果
     */
    @Override
    public int deleteFitnessPlanByPlanIds(String[] planIds)
    {
        return fitnessPlanMapper.deleteFitnessPlanByPlanIds(planIds);
    }

    /**
     * 删除健身计划信息
     * 
     * @param planId 健身计划主键
     * @return 结果
     */
    @Override
    public int deleteFitnessPlanByPlanId(String planId)
    {
        return fitnessPlanMapper.deleteFitnessPlanByPlanId(planId);
    }

    /**
     * 查询今日健身计划
     *
     * @param type
     * @return 结果
     */
    @Override
    public List selectFitnessPlan(String type) {
        List list;
        String today = DateUtils.getDate();
        try {
            list = redisCache.getCacheList(SecurityUtils.getUserId() + "_todayPlan_"+ today);
        } catch (RedisCommandExecutionException | RedisSystemException e) {
            throw new ServiceException("获取有误，请重新获取");
        }
        if (list.isEmpty() || REFRESH.equals(type)) {
            FitnessPlan fitnessPlan = fitnessPlanMapper.selectFitnessPlanInTimeScopeHighest(new FitnessPlan(){
                {
                    setPlanBeg(DateUtils.getNowDate());
                    setCreateUser(SecurityUtils.getUserId());
                }
            });
            if (fitnessPlan == null) {
                throw new ServiceException("当前没有健身计划，请先添加");
            }
            List infos = parseArray(fitnessPlan.getPlanInfo(), Map.class);
            list = calculationTodayPlan(infos);

            redisCache.deleteObject(SecurityUtils.getUserId() + "_todayPlan_" + today);
            redisCache.setCacheList(SecurityUtils.getUserId() + "_todayPlan_" + today, list);
            //3天过期
            redisCache.expire("todayPlan_" + today,3,TimeUnit.DAYS);
        }
        return list;
    }

    /**
     * 修改今日健身计划
     * @return
     */
    @Override
    public boolean updateTodayPlan(SysDictData sysDictData) {
        List<SysDictData> list = redisCache.getCacheList(SecurityUtils.getUserId() + "_todayPlan_"+ today);
        //2为接受，其余为未接受，点击进行切换并刷新缓存
        list.stream().filter(dto-> dto.getDictValue().equals(sysDictData.getDictValue())).forEach(dto-> {
            if (FINISH.equals(dto.getStatus())) {
                dto.setStatus(NOT_FINISH);
            } else {
                dto.setStatus(FINISH);
            }
        });
        redisCache.deleteObject(SecurityUtils.getUserId() + "_todayPlan_" + today);
        redisCache.setCacheList(SecurityUtils.getUserId() + "_todayPlan_" + today, list);
        return true;
    }

    /**
     * 随机获取今日健身计划
     * @param infos
     * @return
     */
    private List<?> calculationTodayPlan(List<Map> infos) {
        List box = new ArrayList();
        int ran = new Random().nextInt(2) + 2;
        for (Map info : infos) {
            int count = Integer.valueOf((String) info.get("value"));
            while (count > 0) {
                box.add(info.get("key"));
                count--;
            }
        }
        String place = (String) RandomUtils.getListRandom(1, box).get(0);
        List<FitnessBasic> types = fitnessBasicMapper.selectFitnessBasicList(new FitnessBasic(){
            {
                setBasicParent(place);
                setCreateBy(SecurityUtils.getLoginUser().getUsername());
            }
        });
        // 有氧一个，无氧2~3个
        if ("aerobics".equals(place)) {
            ran = 1;
        }
        types = (List<FitnessBasic>) RandomUtils.getListRandom(ran, types);
        return types;
    }
}
